package com.fuhao.api.service.impl;

import java.util.Date;
import java.util.Map;

import org.bouncycastle.jcajce.provider.asymmetric.rsa.AlgorithmParametersSpi.OAEP;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.codingapi.tx.annotation.TxTransaction;
import com.fuhao.api.config.AlipayConfig;
import com.fuhao.api.dao.PaymentInfoDao;
import com.fuhao.api.entity.PaymentInfo;
import com.fuhao.api.feign.OrderServiceFeign;
import com.fuhao.api.service.CallBackService;
import com.fuhao.base.BaseApiService;
import com.fuhao.base.ResponseBase;
import com.fuhao.constants.Constants;

import lombok.extern.slf4j.Slf4j;
@RestController
@Slf4j
public class CallBackServiceImpl implements CallBackService{

	@Autowired
	private AlipayConfig alipayConfig;
	@Autowired
	private PaymentInfoDao paymentInfoDao;
	@Autowired
	private OrderServiceFeign orderServiceFeign;
	
	/**
	 * 同步通知实现
	 */
	@Override
	public ResponseBase synCallBack(@RequestParam Map<String, String> params) {
		//日志记录,一般需要把日志记录到数据库中
		log.info("######支付宝同步通知开始######，params：{}"+params);
		//验签
			try {
				boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.alipay_public_key, alipayConfig.charset, alipayConfig.sign_type); //调用SDK验证签名
				log.info("######支付宝验签######，signVerified："+signVerified);
				//——请在这里编写您的程序（以下代码仅作参考）——
				if(!signVerified) {
					return BaseApiService.setResultError("验签失败");
				}
				//商户订单号
				String outTradeNo = params.get("out_trade_no");
			
				//支付宝交易号
				String tradeNo = params.get("trade_no");
			
				//付款金额
				String totalAmount = params.get("total_amount");
				
				
				JSONObject data = new JSONObject();
				data.put("outTradeNo", outTradeNo);
				data.put("tradeNo", tradeNo);
				data.put("totalAmount", totalAmount);
				return BaseApiService.setResultSuccess(data);
			} catch (Exception e) {
				log.error("支付宝同步通知异常");
				return BaseApiService.setResultError("系统错误");
			}finally {
				log.info("######支付宝同步通知结束######，params：{}"+params);
			}
	}

	/**
	 * 异步通知实现
	 * @throws AlipayApiException 
	 */
	@Override
	@Transactional
	@TxTransaction(isStart=true)
	public String asynCallBack(@RequestParam Map<String, String> params) throws AlipayApiException {
		//日志记录,一般需要把日志记录到数据库中
		log.info("######支付宝异步通知开始######，params：{}"+params);
		//验签
//			try {
				boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.alipay_public_key, alipayConfig.charset, alipayConfig.sign_type); //调用SDK验证签名
				log.info("######支付宝异步验签######，signVerified："+signVerified);
				//——请在这里编写您的程序（以下代码仅作参考）——
				if(!signVerified) {
					return "error";
				}
				
				//商户订单号
				String orderNumber = params.get("out_trade_no");
				PaymentInfo paymentInfo = paymentInfoDao.getByOrderIdPayInfo(orderNumber);
				if(paymentInfo == null) {
					return "error";
				}
				//解决支付重试机制产生的幂等性问题，若支付表的状态为1
				//表示已进行业务处理，则不进行执行下面业务逻辑
				Integer payState = paymentInfo.getState();
				if(payState==1) {
					return "error";
				}
				//支付宝交易号
				String payId = params.get("trade_no");
			
				//付款金额
				String totalAmount = params.get("total_amount");
				//为了防止他人而已篡改商品金额，需要判断付款的金额与商品的金额是否一致，
				//若不一致，修改支付状态为异常状态，且把此人支付的金额退还，此处省略
				
				JSONObject data = new JSONObject();
				//#####修改支付表#######
				//修改支付状态
				paymentInfo.setState(1);
				//把回调的所有参数保存到支付日志字段中
				paymentInfo.setPayMessage(params.toString());
				//保存支付宝id号
				paymentInfo.setPlatformorderId(payId);
				//保存时间
//				paymentInfo.setCreated(new Date());
				paymentInfo.setUpdated(new Date());
				Integer updateResult = paymentInfoDao.updatePayInfo(paymentInfo);
				if(updateResult <= 0) {
					return "error";
				}
				//#######修改订单表####
				ResponseBase orderResult = orderServiceFeign.updateOrder(1, payId, orderNumber);
				if(!orderResult.getCode().equals(Constants.HTTP_RES_CODE_200)) {
					//需要回滚updatePayInfo这个操作
					return "error";
				}
				//模拟异常，测试lnc框架是否正常
//				int i = 1/0;
//				System.out.println(i);
				//此处若有一段业务且出错了
				//需要回滚updateOrder和updatePayInfo操作，
				//updateOrder操作，这个是跨数据库的，需要使用到分布式事务解决方案
				return "success";
//			} catch (Exception e) {
				//抛出异常，需要回滚updatePayInfo这个操作
				//若updateOrder也执行完成，也需要回滚，用到分布式事务解决
//				log.error("支付宝同步通知异常:");
//				e.printStackTrace();
//			    return "error";
//			}finally {
//				log.info("######支付宝同步通知结束######，params：{}"+params);
//			}
	}

}
